## GUI handling
import gedit, gobject, gtk
from gettext import gettext as _

import pysvn
import mobwritelib

## For Debugging
import logging
logging.getLogger().setLevel(logging.DEBUG)

SVN_URL = "https://patchwork-editor.googlecode.com/svn/"

ui_str = """<ui>
  <menubar name="MenuBar">
    <menu name="ToolsMenu" action="Tools">
      <placeholder name="ToolsOps_2">
        <menuitem name="Create Branch" action="mnuCreateBranch"/>
        <menuitem name="Open file in branch" action="mnuOpenBFile"/>
      </placeholder>
    </menu>
  </menubar>
</ui>"""

class PatchworkCreateBranchGui(gtk.Dialog):
  def __init__(self, mobClient):
    logging.debug("Creating GUI config")
    gtk.Dialog.__init__(self, "Connect to..")
    
    tmp = gtk.Table(1,1)
    self.vbox.add(tmp)
    tmp.attach(gtk.Label("Branch Name:"),0,1,0,1)
    self.usn = gtk.Entry(max=250)
    self.usn.set_text("test")
    tmp.attach(self.usn, 1,2,0,1)
    self.add_button("Create", 1)
    tmp.show_all()
    self.usn.grab_focus()

class PatchworkOpenBFileGui(gtk.Dialog):
  def __init__(self, mobClient):
    logging.debug("Creating GUI config")
    gtk.Dialog.__init__(self, "Open File..")
    
    tmp = gtk.Table(1,2)
    self.vbox.add(tmp)
    tmp.attach(gtk.Label("Branch Name:"),0,1,0,1)
    self.branch = gtk.Entry(max=250)
    tmp.attach(self.branch, 1,2,0,1)
    tmp.attach(gtk.Label("File Name:"),0,1,1,2)
    self.file = gtk.Entry(max=250)
    tmp.attach(self.file, 1,2,1,2)
    self.add_button("Open", 1)
    tmp.show_all()
    self.branch.grab_focus()

class PatchworkPanelGui(gtk.VBox):
  def __init__(self, helper):
    gtk.VBox.__init__(self)

    def btnconn(btn,cmb):
      branches = helper.getBranches()
      for x in branches:
        cmb.append_text(x)

    def btncrt(btn):
      helper.mnuCreateBranch(None)

    self.list = gtk.combo_box_new_text()

    btn = gtk.Button(label="Refresh Branchlist")
    btn.connect('clicked', btnconn, self.list)
    self.add(btn)

    btn = gtk.Button(label="Create Branch")
    btn.connect('clicked', btncrt)
    self.add(btn)

    self.add(gtk.Label("Branch:"))

    self.filelist = gtk.combo_box_new_text()

    def select_branch(cmb, fl):
      #model, iter = selection.get_selected()
      model = cmb.get_model()
      b = cmb.get_active()
      files = helper.getFiles(model[b][0])
      for y in files:
        fl.append_text(y)


    self.list.connect('changed', select_branch, self.filelist)
    
    self.add(self.list)    


    self.add(gtk.Label("File:"))

    self.add(self.filelist)
    def btnopen(btn,cmb,fl):
      model = cmb.get_model()
      bc = cmb.get_active()
      m = fl.get_model()
      b = fl.get_active()
      helper.openFile(model[bc][0], m[b][0])

    btn = gtk.Button(label="Open")
    btn.connect('clicked', btnopen, self.list, self.filelist)
    self.add(btn)    
    self.show_all()
    
## -------------- ## 
## The Core Class ##
## -------------- ## 

class PatchworkClientInstance:
  def __init__(self, plugin, window):
    # Init Plugin
    logging.debug("Plugins created for %s" % window)
    ## Set up the plugin, Gedit stuff, GTK stuff, and DMP
    self._window = window
    self._plugin = plugin
    ## SVN client
    self.client = pysvn.Client()  

    def get_login( realm, username, may_save ):
      return True, "mikey.be", "Hu6pp4nW9tc8", False
    
    self.client.callback_get_login = get_login

    self._insert_ui()
    

    logging.debug("Loading Complete")

  def openFile(self, branch, filename):  
    filename_hash = branch + "-" + filename
    v = mobwritelib.download("http://neil.fraser.name/scripts/q.py", [filename_hash])
    v = v.get(filename)
    d = self.client.cat(SVN_URL + 'tags/' + branch + '/' + filename)

    if v == None:
      v = ""

    if d != "" and v == "":
      print "uploading"
      success = mobwritelib.upload("http://neil.fraser.name/scripts/q.py", {filename_hash: d})

      if not success:
        sys.exit("Error: MobWrite server failed to respond.")
    ## we know what the text is, maybe a shortcut here?
    self._window.mobc.attach_tab(None, filename_hash)  

  def getFiles(self, branch):    
    dirlist = self.client.list(SVN_URL + 'tags/' + branch)

    d = []
    for tuple in dirlist:
      for dirent in tuple:
        if dirent and dirent["repos_path"] != "/tags/" + branch:
          t = dirent["repos_path"].split("/")[-1]
          d.append(t)
    return d


  def getBranches(self):    
    ent = self.client.ls(SVN_URL + 'tags/')

    lst = ent
    d = []
    for x in lst:
      t = x.name.split("/")[-1]
      d.append(t)
    return d


  def createBranch(self, tag_name):    
    log_message = "create tag " + tag_name
    def get_log_message():
        return True, log_message
    self.client.callback_get_log_message = get_log_message
    self.client.copy(SVN_URL + 'trunk/', SVN_URL + 'tags/%s' % tag_name )    
  
  ## ----------------------------------- ##
  ## --- GUI functions and callbacks --- ##
  ## ----------------------------------- ##
  
  def _insert_ui(self):
    manager = self._window.get_ui_manager()
    
    self._action_group = gtk.ActionGroup("PatchworkActions")
    d = [("mnuCreateBranch", None, _("Create Branch..."), None, _("Open a mobwrite document"), self.mnuCreateBranch),("mnuOpenBFile", None, _("Open branch/file.."), None, _(""), self.mnuOpenBFile)]
    self._action_group.add_actions(d)
    
    manager.insert_action_group(self._action_group, -1)
    self._ui_id = manager.add_ui_from_string(ui_str)
    self._insert_panel()  

  def _remove_ui(self):
    self._remove_panel()
    manager = self._window.get_ui_manager()
    manager.remove_ui(self._ui_id)
    manager.remove_action_group(self._action_group)
    manager.ensure_update()
  
  def update_ui(self):
    self._action_group.set_sensitive(self._window.get_active_document() != None)

  def mnuCreateBranch(self, action):
    box = PatchworkCreateBranchGui(self)
    id = box.run()
    if id == 1:
      u = box.usn.get_text()
      self.createBranch(u)
    box.destroy()

  def mnuOpenBFile(self, action):
    box = PatchworkOpenBFileGui(self)
    id = box.run()
    if id == 1:
      b = box.branch.get_text()
      f = box.file.get_text()
      self.openFile(b,f)
    box.destroy()
    
  def _insert_panel(self):
    self.panel = self._window.get_side_panel()
    self.outlinebox = PatchworkPanelGui(self)
    self.panel.add_item(self.outlinebox, "Python Outline", gtk.STOCK_REFRESH)

  def _remove_panel(self):
    self.panel.destroy()

  ## ------------------------------ ##
  ## --- Gedit plugin functions --- ##
  ## ------------------------------ ##

  def deactivate(self):
    logging.debug("Plugin stopped for %s" % self._window)
    self._remove_ui()
    self._window = None
    self._plugin = None
    self._action_group = None

## ------------------------------------------------------- ##
## This class is created only once. the root plugin class. ##
## ------------------------------------------------------- ##

class PatchworkClientPlugin(gedit.Plugin):
  def __init__(self):
    gedit.Plugin.__init__(self)
    self._instances = {} # Instances of WindowHelper

  def activate(self, window):
    self._instances[window] = PatchworkClientInstance(self, window)

  def deactivate(self, window):
    self._instances[window].deactivate()
    del self._instances[window]
	  
  def update_ui(self, window):
    self._instances[window].update_ui()
